#include "pcm2g711.h"


char ALawEncode(short pcm16)
{
	short p = pcm16;
	char a;  // A-law value we are forming
	if(p<0)
	{
		// -ve value
		// Note, ones compliment is used here as this keeps encoding symetrical
		// and equal spaced around zero cross-over, (it also matches the standard).
		p = ~p;
		a = 0x00; // sign = 0
	}
	else
	{
		// +ve value
		a = 0x80; // sign = 1
	}
	
	// Calculate segment and interval numbers
	p >>= 4;
	if(p>=0x20)
	{
		if(p>=0x100)
		{
			p >>= 4;
			a += 0x40;
		}
		if(p>=0x40)
		{
			p >>= 2;
			a += 0x20;
		}
		if(p>=0x20)
		{
			p >>= 1;
			a += 0x10;
		}
	}
	// a&0x70 now holds segment value and 'p' the interval number
	a += p;  // a now equal to encoded A-law value
	return a^0x55;	// A-law has alternate bits inverted for transmission
}



short ALawDecode(char alaw)
{
	char sign;
	short linear;
	char shift;
	
	alaw ^= 0x55;  // A-law has alternate bits inverted for transmission
	sign = alaw&0x80;
	
	linear = alaw&0x1f;
	linear <<= 4;
	linear += 8;  // Add a 'half' bit (0x08) to place PCM value in middle of range
	
	alaw &= 0x7f;
	if(alaw>=0x20)
	{
		linear |= 0x100;  // Put in MSB
		shift = (alaw>>4)-1;
		linear <<= shift;
	}
	
	if(!sign)
		return -linear;
	else
		return linear;
}